#pragma once
#include "Log.hpp"
#include "INETADDR.hpp"
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#include <memory>
#include <sstream>
#include "Socket.hpp"
#include <jsoncpp/json/json.h>
class Request
{
public:
    Request() {}
    Request(int x, int y, char operate) : _x(x), _y(y), _operate(operate)
    {
    }
    string Serialize()
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["operate"] = _operate;
        Json::StyledWriter writer;
        string s = writer.write(root);
        return s;
    }
    bool Deserialize(string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (!ok)
        {
            return false;
        }
        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _operate = root["operate"].asInt();
        return true;
    }
    int X() { return _x; }
    int Y() { return _y; }
    char Oper() { return _operate; }
    ~Request() {}

private:
    int _x;
    int _y;
    char _operate; // + - * / % -> _x _operate _y -> 10 + 20
};
class Respond
{
public:
    Respond() {}
    Respond(int result, int code)
        : _result(result), _code(code)
    {
    }
    string Serialize()
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::StyledWriter writer;
        string s = writer.write(root);
        return s;
    }
    bool Deserialize(string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (ok)
        {
            _result = root["result"].asInt();
            _code = root["code"].asInt();
            return true;
        }
        return false;
    }
    void SetResult(int res)
    {
        _result = res;
    }
    void SetCode(int code)
    {
        _code = code;
    }
    void ShowResult()
    {
        cout << "计算结果是: " << _result << "[" << _code << "]" << endl;
    }
    ~Respond() {}

private:
    int _result; // 运算结果，无法区分清楚应答是计算结果，还是异常值
    int _code;   // 0:sucess, 1,2,3,4->不同的运算异常的情况
};
const string separator = "\r\n";
using func_t = function<Respond(Request &req)>;
class Protocol
{
public:
    Protocol() {}
   
   
    Protocol(func_t fun)
        : _func(fun) {}
    // 100\r\n{...}\r\n
    string Encode(const string &json_str)
    {
        string len = to_string(json_str.size());
        string str = len + separator + json_str + separator;
        return str;
    }
    bool DeCode(string &buffer, string *package)
    {
        auto pos = buffer.find(separator);
        if (pos == string::npos)
        {
            return false;
        }
        // 100\r\n{...}\r\n
        string json_str_len = buffer.substr(0, pos);
        int len_json_connent = stoi(json_str_len);
        string json_connent = buffer.substr(pos + separator.size(), len_json_connent);
        int totol_json_str = len_json_connent + 2 * separator.size();
        if (buffer.size() < totol_json_str)
            return false;
        *package = buffer.substr(json_str_len.size() + separator.size(), len_json_connent);
        buffer.erase(0, totol_json_str);
        return true;
    }
    void GetRequest(shared_ptr<Socket> &sock, INETADDR &client)
    {
        string buffer_queue;
        while (true)
        {

            int n = sock->Recv(&buffer_queue);
            if (n < 0)
            {
                LOG(LogLevel::WARNING) << client.StringAddr() << "recv erro";
                exit(RECV_ERRO);
                break;
            }
            else if (n == 0)
            {
                LOG(LogLevel::WARNING) << client.StringAddr() << "  client exit...";
                break;
            }
            else
            {
                std::cout << "-----------request_buffer--------------" << std::endl;
                std::cout << buffer_queue << std::endl;
                std::cout << "------------------------------------" << std::endl;
                string json_package;
                while (DeCode(buffer_queue, &json_package))
                {
                    LOG(LogLevel::DEBUG) << client.StringAddr() << " 请求: " << json_package;
                    Request req;
                    bool ok = req.Deserialize(json_package);
                    if (!ok)
                        continue;
                    Respond resp = _func(req);
                    string json_str = resp.Serialize();
                    string send_str = Encode(json_str);
                    sock->Send(send_str);
                }
            }
        }
    }
    bool GetRespond(shared_ptr<Socket> &client, string &resp_buff, Respond *resp)
    {
        
        while (true)
        {
            int n = client->Recv(&resp_buff);
            if (n > 0)
            {

             
                string json_package;
                

                while (DeCode(resp_buff, &json_package))
                {
                    resp->Deserialize(json_package);
                }
                return true;
            }
            else if (n == 0)
            {
               cout << "server quit " << endl;
                return false;
            }
            else
            {
               cout << "recv error" << endl;
                return false;
            }
        }
    }
    string BuildRequestString(int x, int y, char oper)
    {
       
        Request req(x, y, oper);

       
        string json_req = req.Serialize();

      
        return Encode(json_req);
    }
    ~Protocol() {}

private:
    func_t _func;
};